'************************************************************************************
' Copyright  2003-2005 Kathleen Dollard
'
' This software is provided 'as-is', without any express or implied warranty. In no 
' event will the author be held liable for any damages arising from the use of this
' software.
' 
' You may use this software for any purpose, including commercial applications, 
' and you may redistribute this software as part of application delivery: however, 
' this copyright notice may not be removed and you may not otherwise redistribute 
' this software directly other than providing a link to wwww.gendotnet.com. 
'
' You may alter this software to better server your needs (I'd like to hear about your 
' changes in order to make the software better). If you alter the softwre, you must  
' clearly mark it as altered and must not be misrepresented as the original software.
' nor wholly your original work.
'*************************************************************************************
'  Summary: Main file for managing the Generation process

Option Strict On
Option Explicit On 

Imports System

'! Class Summary: 
Namespace KADGen.CodeGenerationSupport
   Public Class Generation

      '#Region "Class level declarations"
      '#End Region

#Region "Public and Friend Methods and Properties"

       Public Sub RunGeneration( _
                    ByVal drivingDoc As CodeGenerationHarness.DrivingDoc, _
                    ByVal callBack As Utility.IProgressCallback, _
                    ByVal xmlDocFileName As String)
         ' Rewritten to simplify nad support DrivingDoc 10/30/04 KAD
         Dim cntNodes As Int32
         Dim sections() As CodeGenerationHarness.DrivingSectionElement
         Dim currentDirName As String
         Dim userDirective As CodeGenerationHarness.UserDirectiveElement
         Dim userSection As CodeGenerationHarness.UserSectionElement
         Dim statusDoc As IStatusDoc = Nothing
         Dim statusSection As IStatusSection
         Dim statusDirective As IStatusDirective
         Dim docPath As String
         Dim runUtility As runUtility
         Dim localSettings As localSettings
         Dim projectSettings As projectSettings
         Dim sourceControl As Utility.SourceControlBase
         Dim cntDone As Int32

         Try
            ' Set directory to restore at end of process, then set current directory
            currentDirName = Environment.CurrentDirectory
            docPath = IO.Path.GetDirectoryName(xmlDocFileName)
            Environment.CurrentDirectory = IO.Path.GetFullPath(docPath)

            ' Set modules values - most of which I'd like to can later
            localSettings = GetLocalSettings(drivingDoc, drivingDoc.GetNsMgr)
            projectSettings = GetProjectSettings(drivingDoc, drivingDoc.GetNsMgr)
            sourceControl = Utility.SourceControlBase.GetSourceControl(IO.Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath))
            'mNodeFilePaths = drivingDoc.SelectSingleNode("kg:GenerationScript/kg:FilePaths", _
            '                     drivingDoc.NsMgr)
            runUtility = New runUtility(projectSettings, sourceControl)

            sections = drivingDoc.Sections
            cntNodes = drivingDoc.DirectiveCheckedCount
            For Each section As CodeGenerationHarness.DrivingSectionElement In sections
               userSection = section.GetUserSection()
               statusSection = section.GetStatusSection()
               If statusDoc Is Nothing Then
                  statusDoc = statusSection.StatusDoc
                  statusDoc.Status = OutputStatus.InProgress
               End If
               If Not userSection.IsChecked Then
                  ' KADLOG:
               Else
                  ' KADLOG:
                  For Each directive As CodeGenerationHarness.DrivingDirective In section.Directives
                     userDirective = directive.GetUserDirective()
                     statusDirective = directive.GetStatusDirective()
                     statusDirective.ClearOutputs()
                     statusDirective.Status = OutputStatus.InProgress
                     ' KADLOG: Log this stuff
                     ' KADLOG: mCurrentOutput = New Utility.OutputInfo
                     ' KADLOG: mCurrentOutput.Section = section.DrivingName
                     ' KADLOG: mCurrentOutput.DirectiveName = directive.DrivingName
                     ' KADLOG: mCurrentOutput.DirectiveType = directive.Name
                     If Not userDirective.IsChecked Then
                        ' KADLOG
                        ' KADLOG: mCurrentOutput.Status = "Not Checked"
                        ' KADLOG: mCntDone = 0
                        statusDirective.Status = OutputStatus.NotChecked
                     Else
                        cntDone += 1
                        If Me.GetCancel(callBack) Then
                           ' KADLOG
                           Exit For
                        Else
                           Me.UpdateStatus(callBack, cntNodes, cntDone)
                           ' KADLOG: callBack.UpdateCurrentNode(CType(nodeItDirective.Current, Xml.IHasXmlNode).GetNode)
                           ' KADLOG: callBack.UpdateCurrentFile("")
                           RunGenerationNode(directive, runUtility, statusDirective)
                           Me.UpdateStatus(callBack, cntNodes, cntDone)
                        End If
                        statusDirective.Status = statusDirective.ChildStatus
                     End If
                  Next
               End If
               statusSection.Status = statusSection.ChildStatus
               'Status = runUtility.MaxStatus(Status, statusSection.Status)
            Next

            ' Pop current directory
            Environment.CurrentDirectory = currentDirName
            If Not statusDoc Is Nothing Then
               statusDoc.Status = statusDoc.ChildStatus
            End If
         Catch ex As System.Exception
            callBack.ThreadExceptionOccurred(ex)
            ' KADLOG
            Throw
         End Try
      End Sub

      Private Function GetCancel(ByVal callback As Utility.IProgressCallback) As Boolean
         If callback IsNot Nothing Then
            Return callback.GetCancel
         End If
      End Function

      Private Sub UpdateStatus( _
               ByVal callback As Utility.IProgressCallback, _
               ByVal cntNodes As Int32, _
               ByVal cntDone As Int32)
         If callback IsNot Nothing Then
            Dim percentDone As Int32
            If cntNodes = 0 Then
               callback.UpdateProgress(100)
            Else
               percentDone = CInt(100 * cntDone / cntNodes)
               If percentDone > 100 Then
                  percentDone = 100
               End If
               callback.UpdateProgress(percentDone)
            End If
         End If
      End Sub
#End Region

#Region "Private Methods and Properties"

      Private Function GetLocalSettings( _
                        ByVal xmlDoc As Xml.XmlDocument, _
                        ByVal nsmgr As Xml.XmlNamespaceManager) _
                        As LocalSettings
         Dim sLocalFile As String
         Dim elem As Xml.XmlNode
         Dim xmlLocalDoc As New Xml.XmlDocument
         Dim localSettings As New localSettings
         elem = xmlDoc.SelectSingleNode("kg:GenerationScript", nsmgr)
         nsmgr.AddNamespace("kl", "http://kadgen.com/KADGenLocalSettings.xsd")
         sLocalFile = Utility.Tools.GetAttributeOrEmpty(elem, "LocalSettings")
         If IO.File.Exists(sLocalFile) Then
            xmlLocalDoc.Load(sLocalFile)
            localSettings.Node = xmlLocalDoc.SelectSingleNode("//kl:LocalSettings", nsmgr)
         End If
         Return localSettings
      End Function

      Private Function GetProjectSettings( _
                        ByVal xmlDoc As Xml.XmlDocument, _
                        ByVal nsmgr As Xml.XmlNamespaceManager) _
                        As ProjectSettings
         Dim sProjectFile As String
         Dim elem As Xml.XmlNode
         Dim xmlLocalDoc As New Xml.XmlDocument
         Dim projectSettings As New projectSettings
         elem = xmlDoc.SelectSingleNode("kg:GenerationScript", nsmgr)
         sProjectFile = Utility.Tools.GetAttributeOrEmpty(elem, "ProjectSettings")
         If IO.File.Exists(sProjectFile) Then
            xmlLocalDoc.Load(sProjectFile)
            nsmgr.AddNamespace("kp", "http://kadgen.com/KADGenProjectSettings.xsd")
            projectSettings.Node = xmlLocalDoc.SelectSingleNode("//kp:ProjectSettings", nsmgr)
         End If
         Return projectSettings
      End Function

      Private Sub RunGenerationNode( _
                     ByVal drivingDirective As CodeGenerationHarness.DrivingDirective, _
                     ByVal runUtility As RunUtility, _
                     ByVal directiveStatus As IStatusDirective)
         Dim methodInfo As Reflection.MethodInfo
         Dim type As System.Type
            Dim obj As System.Object
            If drivingDirective.LocalName <> "Standard" Then
               type = Utility.Tools.GetSpecifiedType(GetType(Generation).Assembly, drivingDirective.LocalName)
               If Not type Is Nothing Then
                  obj = System.Activator.CreateInstance(type)
                  methodInfo = type.GetMethod("Run", Reflection.BindingFlags.Instance Or Reflection.BindingFlags.Static Or Reflection.BindingFlags.IgnoreCase Or Reflection.BindingFlags.Public Or Reflection.BindingFlags.NonPublic)
                  If Not methodInfo Is Nothing Then
                     methodInfo.Invoke(obj, New Object() {drivingDirective, runUtility, directiveStatus})
                  End If
               End If
            End If
      End Sub


#End Region
   End Class
End Namespace